/**
 * Make sure that String has a trim function
 */
if(!String.prototype.trim){
	String.prototype.trim = function() {
		var s = this;
		var w = ' \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000';
		for (var i = 0; i < s.length; i++) {
			if (w.indexOf(s.charAt(i)) === -1) {
				s = s.substring(i);
				break;
			}
		}
		for (i = s.length - 1; i >= 0; i--) {
			if (w.indexOf(s.charAt(i)) === -1) {
				s = s.substring(0, i + 1);
				break;
			}
		}
		return w.indexOf(s.charAt(0)) === -1 ? s : '';
	}
}
/**
 * Definitions for Linquid
 */
linq = lqd = {
	/**
	 * Each
	 * @param o	The set to iterate over
	 * @param f The action to perform on each item (String or Function)
	 */
	f: function(o, f){var uf=lqd.Z(f); for(i=0;i<o.length;i++)uf(o[i]);},
	/**
	 * Where
	 * @param o	The set to iterate over
	 * @param f The predicate that must be satisfied to return the item (String or Function)
	 * @return A linquified array containing the elements that satisfied the predicate
	 */
	w: function(o, f){
		var a=[];
		var uf=lqd.Z(f);
		for(var i=0;i<o.length;i++)
			if(uf(o[i], i))a.push(o[i]);
		return a;
	},
	/**
	 * All
	 * @param o The set to iterate over
	 * @param f (Optional: Default x=>x) The predicate that must be satisfied on all items (String or Function)
	 * True if all the items satisfy the predicate
	 */
	a: function(o, f){
		var r = true;
		var uf=lqd.Z(f||"x=>x");
		for(var i=0;r&&i<o.length;i++)r&=uf(o[i]);
		return r;
	},
	/**
	 * Any
	 * @param o The set to iterate over
	 * @param f (Optional: Default x=>x) The predicate that must be satisfied on at least one item (String or Function)
	 * @return True if at least one item satisfied the predicate
	 */
	b: function(o, f){
		var r = false;
		var uf=lqd.Z(f||"x=>x");
		for(var i=0;!r&&i<o.length;i++)r|=uf(o[i]);
		return r;
	},
	/**
	 * Aggregate
	 * @param o The set to iterate over
	 * @param f (Optional: Default function(r, i){ return r[i];}) The selector for the element to be included in the aggregate (String or Function)
	 * @return A linquified array containing the result
	 */
	c: function(o, f){
		var a=[];
		var uf=lqd.Z(f||"x=>x");
		for(var i=0;i<o.length;i++){
			var foi=uf(o[i]);
			for(var j=0;j<foi.length;j++)
				a.push(foi[j]);
		}
		return a;
	},
	/**
	 * First
	 * @param o The set to get the first element of
	 * @param f (Optional: Default x=>x) The method used to filter the set to relevant records
	 * @return The first element of the set, throws an exception if the set has no elements
	 */
	d: function(o, f) {
		return (f?linq.w(o, f)[0]:o[0]);
	},
	/**
	 * FirstOrDefault
	 * @param o	The set to get the first element of
	 * @param f (Optional: Default x=>x) The method used to filter the set to relevant records
	 * @return The first element of the set if the set has at least one element, null otherwise
	 */
	e: function(o, f){
		var n = (f ? linq.w(o, f) : o);
		return n.length>0?n[0]:null;
	},
	/**
	 * Contains
	 * @param o The set to search in
	 * @param e The element to search for
	 * @param eq (Optional: Default (a,b) => a == b) The method to use to determine the (in)equality of two members (String or Function)
	 * @return True if the element is found in the set
	 */
	s: function(o, e, eq){
		return lqd.g(o, e,eq)>-1;
	},
	/**
	 * IndexOf
	 * @param o	The set to search in
	 * @param e The element to search for
	 * @param eq (Optional: Default (a,b) => a == b) The method to use to determine the (in)equality of two members (String or Function)
	 * @return The index of the element in the set or -1 if not found
	 */
	g: function(o, e,eq){
		var f=lqd.Z(eq||function(x,y){return x==y;});
		for(var i=0;i<o.length;i++)if(f(o[i],e))return i;
		return -1;
	},
	/**
	 * Reverse
	 * @param o	The set to reverse
	 * @return A linquified array containing the members of the original set in reverse order
	 */
	h: function(o){
		var a=[];
		for(var c=o;c.length>0;a.push(c.pop()));
		return a;
	},
	/**
	 * Last
	 * @param o	The set to get the last element of
	 * @param f (Optional: Default x=>x) The method used to filter the set to relevant records
	 * @return The last element in the set, throws an exception if the set is empty
	 */
	i: function(o,f){
		var n = (f?linq.M(o,f):o);
		return n[n.length-1];
	},
	/**
	 * LastOrDefault
	 * @param o The set to get the last element of
	 * @param f (Optional: Default x=>x) The method used to filter the set to relevant records
	 * @return The last element in the set or null if the set is empty
	 */
	j: function(o,f){
		var res=(f?linq.M(o,f):o);
		return res.length>0?res[res.length-1]:null;
	},
	/**
	 * Max
	 * @param o	The set to get the maximum value from
	 * @param f (Optional: Default x=>x) The function to use to select the value for comparison in the set (String or Function)
	 * @param eq (Optional: Default function(a,b){return a>b?1:a<b?-1:0;}) The function used to compare values in the set (String or Function)
	 * @return The element having the maximum value
	 */
	k: function(o, f, eq){
		return lqd.j(lqd.o(o, f, eq));
	},
	/**
	 * Min
	 * @param o	The set to get the minimum value from
	 * @param f (Optional: Default x=>x) The function to use to select the value for comparison in the set (String or Function)
	 * @param eq (Optional: Default function(a,b){return a>b?1:a<b?-1:0;}) The function used to compare values in the set (String or Function)
	 * @return The element having the minimum value
	 */
	l: function(o, f, eq){
		return lqd.j(lqd.p(o, f, eq));
	},
	/**
	 * OrderBy
	 * @param o The set to order the elements of
	 * @param f (Optional: Default x=>x) The function to use to select the value for comparison in the set (String or Function)
	 * @param eq (Optional: Default function(a,b){return a>b?1:a<b?-1:0;}) The function used to compare values in the set (String or Function)
	 * @return A linquified array of the ordered items
	 */
	o: function(o, f, eq){
		u = lqd.Z(f||"x=>x");
		ueq = lqd.Z(eq||function(a,b){return a>b?1:a<b?-1:0;});
		return o.sort(function(a,b){var fa=u(a);var fb=u(b); return ueq(fa, fb)});
	},
	/**
	 * OrderByDescending
	 * @param o The set to order the elements of
	 * @param f (Optional: Default x=>x) The function to use to select the value for comparison in the set (String or Function)
	 * @param eq (Optional: Default function(a,b){return a>b?1:a<b?-1:0;}) The function used to compare values in the set (String or Function)
	 * @return A linquified array of the ordered items
	 */
	p: function(o, f, eq){
		var ieq = lqd.Z(eq||function(a,b){return a>b?1:a<b?-1:0;});
		var ueq = function(a,b){return -ieq(a,b);};
		return lqd.o(o, f, ueq);
	},
	/**
	 * Select
	 * @param o	The set to select from
	 * @param f (Optional: Default x=>x) The operation used to transform each element in the set (String or Function)
	 * @return A linquified array containing the result of the transformation on each element
	 */
	q: function(o, f){
		var a=[];
		var u=lqd.Z(f||function(x){return x;});
		var ol=o.length;
		for(var i=0;i<ol;i++)
			a.push(u(o[i], i));
		return a;
	},
	/**
	 * SelectMany
	 * @param o The set to select from
	 * @param f (Optional: Default x=>x) The selector function (String or Function)
	 * @return A projection of each element of a sequence to an Array, flattened
	 */
	N: function(o, f){
		var a=[];
		var u=lqd.Z(f||function(x){return x;});
		var ol=o.length;
		for(var i=0;i<ol;i++){
			var ui=lqd.q(o[i], u);
			var ul=ui.length;
			for(var j=0;j<ul;j++)
				a.push(ui[j]);
		}
		return a;
	},
	/**
	 * Count
	 * @param o The set to count the elements of
	 * @param f (Optional: Default x=>x) The selector for what elements to count
	 * @return The number of elements matching the selector
	 */
	O: function(o, f){
		var uf=lqd.Z(f||"x=>x");
		return lqd.w(o,uf).length;
	},
	/**
	 * DefaultIfEmpty
	 * @param o The set to return if it is populated
	 * @param v (Optional: Default null) The single value to return in a new collection if "o" is empty
	 * @return Whichever collection is not empty
	 */
	P: function(o,v){
		return (o.length>0)?o:[v||null];
	},
	/**
	 * Join
	 * @param o The left hand set
	 * @param o2 The right hand set
	 * @param f The condition that must be satisfied to join two elements (String or Function)
	 * @param m The kind of join to perform (linq.joinKind)
	 * @param slr (Optional: Default false) (Internal use only) Switch left and right outputs
	 * @return A linquified array containing the result of the join, each element in the output has a property "left" and a property "right" which contains the result from each set respectively
	 */
	r: function(o, o2, f, m, slr){
		var um=m||1;
		var uf=lqd.Z(f);
		if(um==3){var res=lqd.r(o2,o,uf,lqd.joinKind.left,true); for(var i=0;i<res.length;i++){var r=res[i].left;res[i].left=res[i].right;res[i].right=r;} return res;}
		var s=
			//inner join
			um==1?function(oi){return lqd.q(lqd.w(o2,function(o2i){return uf(slr?o2i:oi,slr?oi:o2i);}),function(q){return {"left":oi,"right":q};});}
			//left join
		   :function(oi){var res = lqd.w(o2,function(o2i){return uf(slr?o2i:oi,slr?oi:o2i);}); if(res.length==0)res.push(null); return lqd.q(res,function(q){return{"left":oi,"right":q}});};
		return lqd.c(lqd.w(lqd.q(o, s), function(k){return k.length>0;}));
	},
	/**
	 * Sum
	 * @param o	The set to sum over
	 * @param f (Optional: Default x=>x) The function used to select the values to sum on (String or Function)
	 * @return The sum of the selected values
	 */
	t: function(o,f){
		var t=0;
		var u=lqd.Z(f||function(x){return x;});
		for(var i=0;i<o.length;i++)t+=u(o[i]);
		return t;
	},
	/**
	 * Average
	 * @param o The set to average over
	 * @param f (Optional: Default x=>x) The function used to select the values to average (String or Function)
	 * @return The average of the selected values
	 */
	u: function(o,f){
		return lqd.t(o,f)/o.length;
	},
	/**
	 * Concat
	 * @param o The first set
	 * @param a The second set
	 * @return A linquified array representing the concatenated sets
	 */
	v: function(o, a){
		var n=[];
		for(var i=0;i<o.length;i++)n.push(o[i]);
		for(var j=0;j<a.length;j++)n.push(a[j]);
		return n;
	},
	/**
	 * Distinct
	 * @param o	The set to get the distinct values from
	 * @param f (Optional: Default x=>x) The function used to select the value that indicates distinctness (String or Function)
	 * @param eq (Optional: Default (a, b)=> a == b) The function used to determine the (in)equality of two members of the set (String or Function)
	 * @return A linquified array containing the distinct elements from the set
	 */
	x: function(o, f, eq){
		var a=[];
		var k=[];
		var u=lqd.Z(f||function(x){return x;});
		for(var i=0;i<o.length;i++){
			var uoi=u(o[i]);
			if(!lqd.s(k,uoi,eq)){k.push(uoi);a.push(o[i]);}
		}
		return a;
	},
	/**
	 * ElementAt
	 * @param o	The set to get the element from
	 * @param i The index to get the element from
	 * @return The value at index i, if the set does not contain at least i+1 items (or if i is negative) an exception is thrown
	 */
	y: function(o, i){
		return o[i];
	},
	/**
	 * ElementAtOrDefault
	 * @param o The set to get the element from
	 * @param i The index to get the element from
	 * @return The value at index i, or, if i is not an acceptable index for the set, null
	 */
	z: function(o, i){
		return (o.length>i&&i>=0)?o[i]:null;
	},
	/**
	 * GroupBy
	 * @param o The set to group on
	 * @param f The expression used to select the value to group on (String or Function)
	 * @return A linquified array of linquified arrays grouped by key
	 */
	A: function(o, f){
		var uf=lqd.Z(f);
		var d=lqd.x(lqd.q(o, uf));
		var a=[];
		for(var i=0;i<d.length;i++)
			a.push(lqd.w(o,function(q){return d[i]==uf(q);}));
		return a;
	},
	/**
	 * Skip
	 * @param o The set to skip the first elements of
	 * @param c The number of elements to skip
	 * @return A linquified array of elements beyond the first "c" of the set
	 */
	B: function(o,c){
		var a=[];
		for(var i=c;i<o.length;i++)
			a.push(o[i]);
		return a;		
	},
	/**
	 * SkipWhile
	 * @param o The set to skip the first elements of
	 * @param f The predicate that determines whether or not the element will be skipped (String or Function)
	 * @return A linquified array of the elements in the set that exist after the first time "f(o[i])" evaluated to false
	 */
	C: function(o,f){
		var a=[];
		var uf=lqd.Z(f);
		for(var i=0;i<o.length&&uf(o[i]);i++);
		for(;i<o.length;i++)a.push(o[i]);
		return a;
	},
	/**
	 * Take
	 * @param o The set to take elements from
	 * @param c The number of elements to take
	 * @return A linquified array containing the first "c" elements of the set, less elements will be returned if the set does not contain at least "c" elements
	 */
	D: function(o,c){
		var a=[];
		var l=o.length;
		for(var i=0;i<l&&i<c;i++)
			a.push(o[i]);
		return a;
	},
	/**
	 * TakeWhile
	 * @param o The set to take elements from
	 * @param f The predicate that must be satisfied to keep taking elements (String or Function)
	 * @return A linquified array containing the elements from the start of the set that satisfied "f"
	 */
	E: function(o,f){
		var a=[];
		var uf=lqd.Z(f);
		for(var i=0;i<o.length&&uf(o[i]);i++)a.push(o[i]);
		return a;
	},
	/**
	 * Single
	 * @param o	The set to take the only element of
	 * @param f (Optional: Default x=>x) The method used to filter the set to relevant records
	 * @return The only element in the set, throws an exception if there is not exactly one element in the set
	 */
	F: function(o,f){
		var n=(f?linq.w(o,f):o);
		if(n.length>1)throw "More than one element in sequence";
		return n[0];
	},
	/**
	 * SingleOrDefault
	 * @param o	The set to take the only element of
	 * @param f (Optional: Default x=>x) The method used to filter the set to relevant records
	 * @return The only element in the set, or null if there was not exactly one element
	 */
	G: function(o,f){
		var n=(f?linq.w(o,f):o);
		if(n.length!=1)return null;
		return n[0];
	},
	/**
	 * Union
	 * @param o	The first set
	 * @param o2 The second set
	 * @param eq (Optional: Default (a, b)=> a == b) The function used to determine the (in)equality of two members of the set (String or Function)
	 * @return A linquified array containing the distinct elements from the combination of the sets
	 */
	H: function(o,o2,eq){
		return lqd.x(lqd.v(o,o2),null,eq);
	},
	/**
	 * Zip
	 * @param o	The first set
	 * @param o2 The second set
	 * @param f The function used to combine the sequences (String or Function)
	 * @return A linquified array containing the zipped sequence
	 */
	I:function(o, o2, f){
		var uf=lqd.Z(f);
		var a=[];
		for(var i=0;i<o.length&&i<o2.length;i++)a.push(uf(o[i],o2[i]));
		return a;
	},
	/**
	 * SequenceEquals
	 * @param o	The first set
	 * @param o2 The second set
	 * @param eq (Optional: Default (a, b)=> a == b) The equality comparer to use (String or Function)
	 * @param io (Optional: Default false) Whether or not to ignore the order of the elements in the sequences
	 * @return True if neither or both sets are null and (if not null) the elements in the two sequences satisfy the set conditions 
	 */
	J:function(o,o2,eq,io){
		var uf=lqd.Z(eq||function(x,y){return x==y;});
		if(o^o2||o.length!=o2.length)return false;
		var ol=o.length;
		if(io){
			var uo2=[];
			for(var i=0;i<ol;i++){
				var co=o[i];
				var j;
				for(j=0;j<ol;j++){
					if(!lqd.s(uo2,j)&&uf(co,o2[j]))
					{ uo2.push(j); break; }
				}
				if(j==ol&&uo2.length!=ol)return false;
			}
			return true;
		}
		var ct=true;
		for(var i=0;i<ol&&ct;i++)ct=ct&&uf(o[i],o2[i]);
		return ct;
	},
	/**
	 * Intersect
	 * @param o	The first set
	 * @param o2 The second set
	 * @param eq (Optional: Default (a,b)=> a==b) The equality comparer to use (String or Function)
	 * @return A linquified array that containts the elements from the first set that also exist in the second set and no other elements
	 */
	K:function(o,o2,eq){
		var uf=lqd.Z(eq||"(x,y)=>x==y");
		return lqd.w(o,function(x){return lqd.s(o2,x,uf);});
	},
	/**
	 * Except
	 * @param o	The set to get elements from
	 * @param f The function that must evaluate to false for an element for it to be returned (String or Function)
	 * @return A linquified array of elements containing the elements that did not satisfy "f"
	 */
	L:function(o, f){		
		var a=[];
		var uf=lqd.Z(f);
		for(var i=0;i<o.length;i++)
			if(!uf(o[i]))a.push(o[i]);
		return a;
	},
	/**
	 * Reverse order where
	 * @param o The set to get elements from
	 * @param f The function that must evaluate to true for an element to be returned (String or Function)
	 * @return An array of elements containing the elements that satisfied "f"
	 */
	M:function(o, f){
		var a=[];
		var uf=lqd.Z(f);
		for(var i=o.length-1;i>=0;i--){
			if(uf(o[i]))a.push(o[i]);
		}
		return a;
	},
	/**
	 * ToDictionary
	 * @param o The set to get elements from
	 * @param k The function that selects the key of the object (String or Function)
	 * @param v (Optional: Default x=>x) The function that selects the value of the object (String or Function)
	 * @return An object operating as a dictionary
	 */
	Q: function(o,k,v){
		var r = new Object();
		var uk=lqd.Z(k);
		var uv=lqd.Z(v||"x=>x");
		lqd.f(o,function(e){r[uk(e)]=uv(e);});
		return r;
	},
	/**
	 * Converts a construct that has a property called "length" to a linquified array
	 * @param o	The object to convert
	 * @return A linquified array constructed from the values contained on the integers between 0 and o.length (inclusive and exclusive respectively)
	 */
	AsArray: function(o){
		var a=[];
		for(var i=0;i<o.length;i++)a.push(o[i]);
		return lqd._(a);
	},
	/**
	 * Selects the result of the application of the jQuery selector on each element in a set
	 * (jQuery-enabled only feature)
	 * @param o	The set to apply the selector to
	 * @return A linquified array containing the result of the application of the jQuery selector to each element in the set
	 */
	$: function(o){
		return lqd.q(o, $);
	},
	/**
	 * Selects "real" elements from a set.  What is meant by "real" is that if the jQuery selector has been applied to the element, the
	 * matching elements as non-jQuery objects are returned
	 * (jQuery-enabled only feature)
	 * @param o The set to get the "real" elements from
	 * @return A linquified array of the "real" elements
	 */
	_$: function(o){
		return lqd.c(o, "x=>(x.jquery)?lqd.q(x):[x]");
	},
	/**
	 * Handles the availability of (String or Function) type parameters.
	 * Strings are converted to anonymous functions, eval'd and stored in an expression cache so the same expression is never eval'd twice
	 * @param s The String or Function to return as a Function
	 * @return A function representing whatever was passed in
	 */
	Z: function(s){
		if(typeof s != "string") return s;
		if(!lqd.ExprCache)lqd.ExprCache = new Object();
		if(lqd.ExprCache[s]) return lqd.ExprCache[s];
		var g2=s.indexOf("=>");
		var ws="tmp=function("+s.substr(0,g2).trim()+")";
		ws=ws.replace("((","(").replace("))", ")");
		var fp=s.substr(g2+2).trim();
		ws+=(fp.indexOf("{")!=0?"{":"")+((fp.indexOf("{") == -1 && fp.indexOf(";")!=fp.length-1)?"return ":"") +fp+((fp.indexOf("{") == -1 && fp.indexOf(";")==-1)?";":"")+(fp.indexOf("{")!=0?"}":"");
		return lqd.ExprCache[s] = eval(ws); 
	},
	/**
	 * Gets an empty set
	 * @return An empty, linquified set
	 */
	Empty:function(){return _([]);},
	/**
	 * Gets a set containing the value "v" "c" times
	 * @param v The value to repeat
	 * @param c The number of times to repeat the value
	 * @return A linquified array containing the value "v" "c" times
	 */
	Repeat:function(v,c){
		var a=[];
		for(var i=0;i<c;i++)a.push(v);
		return _(a);
	},
	/**
	 * Gets a set containing the values "l" to "h"
	 * @param l The low bound of the range (inclusive)
	 * @param h The high bound of the range (exclusive)
	 * @return A linquified array containing the values "l" to "h" - 1
	 */
	Range:function(l,h){
		var a=[];
		for(var i=l;i<h;i++)a.push(i);
		return a;
	},
	/**
	 * Returns a linquified version of an array
	 * @param o	The array to linquify
	 * @return The linquified array
	 */
	_:function(o) { delete o._linquid; return lqd.mk(o, window["jQuery"]); },
	/**
	 * Linquifies the system!
	 * (Calls linq.uify on Array.prototype and calls linq.uify$)
	 */
	install:function(){
		linq.uify(Array.prototype, window["jQuery"]);
		linq.uify$();
	},
	/**
	 * Installs the linquid methods to jQuery
	 */
	$install:function(){
		if(!window["jQuery"])return;
		var p={length:0};
		lqd.mk(p,true);
		$.fn.extend(p);
	},
	/**
	 * Handles the availability of (String or Function) type parameters.
	 * Strings are converted to anonymous functions, eval'd and stored in an expression cache so the same expression is never eval'd twice
	 * @param s The String or Function to return as a Function
	 * @return A function representing whatever was passed in
	 */
	Expr:function(s){return lqd.Z(s);},
	/**
	 * "Makes" or Installs linquid on an object
	 * @param o	The object to install the linquid methods on
	 * @param jq (Optional: Default false) Whether or not jQuery is present
	 * @return Returns the original object "linquified"
	 */
	mk: function(o, jq) {
		if(!o||typeof o.length=="undefined"||o._linquid)return o;
		o._linquid=true;
		o.All = function(f) { return lqd.a(this, f);};
		o.Any = function(f) { return lqd.b(this, f);};
		o.Aggregate = function(f) { return lqd._(lqd.c(this, f));};
		o.Average = function(f) { return lqd.u(this,f);}
		o.Concat = function(a) { return lqd._(lqd.v(this, a));};
		o.Contains = function(e,eq) { return lqd.s(this, e,eq);};
		o.Count = function(f) { return lqd.O(this, f);};
		o.DefaultIfEmpty = function(v){ return lqd.P(this, v);};
		o.Distinct = function(f,eq) { return lqd._(lqd.x(this, f,eq));};
		o.Each = function(f) { lqd.f(this, f); };
		o.ElementAt = function(i) { return lqd.y(this,i); };
		o.ElementAtOrDefault = function(i){return lqd.z(this,i);};
		o.Except = function(f){return lqd._(lqd.L(this, f));};
		o.First = function(f) { return lqd.d(this,f);};
		o.FirstOrDefault = function(f) { return lqd.e(this,f);};
		o.GroupBy = function(f) { return lqd._(lqd.A(this, f)); };
		o.IndexOf = function(e,eq) { return lqd.g(this, e,eq);};
		o.Intersect = function(o,eq){return lqd._(lqd.K(this,o,eq));}
		o.Join = function(other, condition, kind) { return lqd._(lqd.r(this, other, condition, kind));};
		o.Last = function(f) { return lqd.i(this,f);};
		o.LastOrDefault = function(f) { return lqd.j(this,f);};
		o.LongCount = function(f) { return lqd.O(this,f);};
		o.Max = function(f,eq) { return lqd.k(this,f,eq);};
		o.Min = function(f,eq) { return lqd.l(this,f,eq);};
		o.OfTagType = function(t) { return lqd._(lqd.w(this, function(o) { return o.tagName&&o.tagName.toLowerCase() == t;}));};
		o.OfType = function(t) { return lqd._(lqd.w(this, function(o) { return typeof o == t;}));};
		o.OrderBy = function(f, eq) { return lqd._(lqd.o(this, f, eq)); }
		o.OrderByDescending = function(f, eq) { return lqd._(lqd.p(this, f, eq)); }
		o.Reverse = function() { return lqd._(lqd.h(this));};
		o.Select = function(f) { return lqd._(lqd.q(this,f));};
		o.SelectMany = function(f) { return lqd._(lqd.N(this,f));}
		o.SequenceEquals=function(other,f,ignoreOrder){return lqd._(lqd.J(this,other,f,ignoreOrder));};
		o.Single = function(f){return lqd.F(this,f);};
		o.SingleOrDefault=function(f){return lqd.G(this,f);};
		o.Skip = function(c) { return lqd._(lqd.B(this, c));};
		o.SkipWhile = function(f){return lqd._(lqd.C(this,f));};
		o.Sum = function(f) { return lqd.t(this,f);};
		o.Take = function(c) { return lqd._(lqd.D(this,c));};
		o.TakeWhile = function(f){return lqd._(lqd.E(this,f));};
		o.ToDictionary = function(keySel, valSel){return lqd.Q(this,keySel,valSel);};
		o.Union = function(other,eq){return lqd._(lqd.H(this,other,eq));};
		o.Where = function(f) { return lqd._(lqd.w(this, f));};
		o.Zip = function(other,f) { return lqd._(lqd.I(this,other,f));};
		if(jq){o.$ = function() { return lqd._(lqd.$(this));};o._$ = function() { return lqd._(lqd._$(this));};}
		return o;
	},
	/**
	 * "Unmakes" or uninstalls linquid methods from an object
	 * @param o	The object to uninstall linquid methods from
	 * @param jq (Optional: Default false) Whether or not jQuery is present
	 */
	um: function(o,jq){
		if(!o||typeof o.length=="undefined"||!o._linquid)return o;
		delete o._linquid;
		delete o.All;
		delete o.Any;
		delete o.Aggregate;
		delete o.Average;
		delete o.Concat;
		delete o.Contains;
		delete o.Count;
		delete o.LongCount;
		delete o.DefaultIfEmpty;
		delete o.Distinct;
		delete o.Each;
		delete o.ElementAt;
		delete o.ElementAtOrDefault;
		delete o.Except;
		delete o.First;
		delete o.FirstOrDefault;
		delete o.GroupBy;
		delete o.IndexOf;
		delete o.Intersect;
		delete o.Join;
		delete o.Last;
		delete o.LastOrDefault;
		delete o.Max;
		delete o.Min;
		delete o.OfTagType;
		delete o.OfType;
		delete o.OrderBy;
		delete o.OrderByDescending;
		delete o.Reverse;
		delete o.Select;
		delete o.SelectMany;
		delete o.SequenceEquals;
		delete o.Single;
		delete o.SingleOrDefault;
		delete o.Skip;
		delete o.SkipWhile;
		delete o.Sum;
		delete o.Take;
		delete o.TakeWhile;
		delete o.ToDictionary;
		delete o.Union;
		delete o.Where;
		delete o.Zip;
		if(jq) {
			delete o.$;
			delete o._$;
		}
		return o;
	},
	/**
	 * Supported join kinds
	 */
	joinKind: {
		/**
		 * Inner join
		 */
		inner: 1,
		/**
		 * Left (outer) join
		 */
		left: 2,
		/**
		 * Right (outer) join
		 */
		right: 3
	}
};
/**
 * Install linquid
 * @param o	(Optional: Default Array.prototype) The object to install linquid to
 * @return If "o" was specified, null, otherwise the linquified array
 */
linq.uify=function(o){if(!o){lqd.install();return;}return lqd.mk(o,window["jQuery"]);};
/**
 * Installs the linquid jQuery extensions
 */
linq.uify$=function(){lqd.$install();};
/**
 * Special handling for a window level flag called linquidAuto
 * If an included script defines this, linq.uify is called automagically
 */
if(window["linquidAuto"]){linq.uify();}
/**
 * Container for unlinquifying things
 * Mainly to stick with the clever name
 */
unlinq={
	/**
	 * Unlinquify something
	 */
	uify:function(o){if(!o){lqd.uninstall();return;}return lqd.um(o,window["jQuery"]);}
};
